package com.tianlan.blog.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tianlan.blog.dto.LoginUser;
import com.tianlan.blog.dto.UserInfo;
import com.tianlan.blog.entity.SysResource;
import com.tianlan.blog.entity.SysRole;
import com.tianlan.blog.entity.SysUser;
import com.tianlan.blog.service.SysResourceService;
import com.tianlan.blog.service.SysUserRoleService;
import com.tianlan.blog.service.SysUserService;
import com.tianlan.common.annotation.auth.CurrentUser;
import com.tianlan.common.annotation.auth.NoAuthentication;
import com.tianlan.common.base.Constant;
import com.tianlan.common.base.ResponseConstant;
import com.tianlan.common.base.Result;
import com.tianlan.common.base.component.JwtComponent;
import com.tianlan.common.captcha.GifCaptcha;
import com.tianlan.common.captcha.util.CaptchaUtil;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;


@RestController
@RequestMapping(value = "/auth")
public class LoginController {
	
	private static final Logger log = LogManager.getLogger(LoginController.class);
    
	@Autowired
    private SysUserService userService;
	
    @Autowired
    private JwtComponent jwtComponent;
    
    @Autowired
    private SysUserRoleService sysUserRoleService;
    
    @Autowired
    private SysResourceService sysResourceService;

    @GetMapping("/vcode")
    @NoAuthentication
    @ApiOperation(value = "获取登录时的验证码")
    @ApiImplicitParam(paramType = "query", name = "codeKey", value = "验证码唯一标识", required = true, dataType = "String")
    public void defaultKaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String codeKey = request.getParameter("codeKey");
        if (codeKey != null && !codeKey.trim().isEmpty()) {
            response.setContentType("image/gif");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0L);
            GifCaptcha captcha = new GifCaptcha(130, 38, 5);
            ServletContext servletContext = request.getSession().getServletContext();
            servletContext.setAttribute("code_" + codeKey, captcha.text().toLowerCase());
            captcha.out(response.getOutputStream());
        }
    }
    
    @PostMapping("/login")
    @NoAuthentication
    @ApiOperation(value = "执行登录", notes = "返回token")
    public Result<String> login(@RequestBody LoginUser loginUser, HttpServletRequest request){
        String userAccount = loginUser.getUserAccount();
        String userPassword = loginUser.getUserPassword();
        String vcode = loginUser.getVcode();
        String verkey = loginUser.getVerkey();
           if (!CaptchaUtil.isVerified(verkey, vcode, request)) {
            return new Result<String>().error(ResponseConstant.INVALID_RE_VCODE);
        }
        if (StringUtils.isEmpty(userAccount) || StringUtils.isEmpty(userPassword)) {
            return new Result<String>().error(ResponseConstant.PARAM_ERROR);
        }    
		SysUser user = userService.getUserByUserAccount(userAccount);		
		String loginPassWord = new Sha256Hash(userPassword, user.getSalt()).toHex();
		if(user == null || !user.getUserPassword().equals(loginPassWord)) {
			return new Result<String>().error("用户帐号或密码不正确");
		}
		if(user.getUserStatus().equals("0")){
			return new Result<String>().error("账号已被锁定,请联系管理员");
		}
      try {        
        String tokenSession = jwtComponent.sign(userAccount, user.getUserPassword() + user.getSalt(), Constant.ExpTimeType.WEB);
        return new Result<String>().success().put(tokenSession);
      
      } catch ( UnknownAccountException uae ) {
          log.warn("用户帐号不正确");
          return new Result<String>().error("用户帐号或密码不正确");

      } catch ( IncorrectCredentialsException ice ) {
          log.warn("用户密码不正确");
          return new Result<String>().error("用户帐号或密码不正确");

      } catch ( LockedAccountException lae ) {
          log.warn("用户帐号被锁定");
          return new Result<String>().error("用户帐号被锁定不可用");

      } catch ( AuthenticationException ae ) {
          log.warn("登录出错");
          return new Result<String>().error("登陆失败："+ae.getMessage());
      }
    }
    
    /**
     * 获取登录后的用户信息
     */
    @GetMapping("/user/info")
    @RequiresAuthentication
    @ApiOperation(value = "登录后获取用户个人信息")
    public Result<UserInfo> userInfo(HttpServletRequest request,@ApiIgnore @CurrentUser SysUser currentUser) {
    	Integer userId = currentUser.getId();
    	UserInfo userInfo = new UserInfo();
    	BeanCopier.create(SysUser.class, UserInfo.class, false).copy(currentUser, userInfo, null);
    	List<SysRole> roleList = sysUserRoleService.queryRolesByUserId(userId);
    	if (!CollectionUtils.isEmpty(roleList)) {
    		List<String> roles = new ArrayList<String>();
    		StringBuffer roleNames = new StringBuffer();
    		for(SysRole sysRole:roleList){
    			roles.add(sysRole.getRoleKey());
    			roleNames.append(sysRole.getRoleName());
    		}
    		userInfo.setRoles(roles);
            userInfo.setRoleName(roleNames.toString());
    	}
    	List<SysResource> sysResourceList = sysResourceService.queryResourceByUserId(userId);
    	userInfo.setResources(sysResourceList);
    	
    	List<String> sysResourceStringList =sysResourceService.queryResourceListByUserId(userId);
    	userInfo.setStringResources(sysResourceStringList);
    	
    	return new Result<UserInfo>().success().put(userInfo);
    }
    

    @PostMapping("/logout")
    @NoAuthentication
    @ApiOperation(value = "退出登录")
    public Result<?> logOut(HttpServletRequest request) throws Exception {
        return new Result<>().success();
    }
    
    @RequestMapping("401")
    @NoAuthentication
    @ApiIgnore
    public Result<?> unauthorized() {
        return new Result<>().error(ResponseConstant.USER_NO_PERMITION);
    }
    
    @RequestMapping("/timeout")
    @NoAuthentication
    @ApiIgnore
    public Result<?> timeOut() {
        return new Result<>().error(ResponseConstant.UNAUTHORIZED);
    }
    
}